#ifndef __FUNCTION_WRAPPER__
#define __FUNCTION_WRAPPER__
#include <iostream>
#include <memory>

using std::unique_ptr;

class function_wrapper
{
private:
    struct  impl_base
    {
        virtual void call() = 0;
        virtual ~impl_base() {}
    };

    unique_ptr<impl_base> _impl; 
    template <typename F>
    struct impl_type : impl_base
    {
        F _f;
        impl_type(F &&f) : _f(std::move(f)) {}
        void call() { _f(); }
    };
public:
    template <typename F>
    function_wrapper(F &&f): _impl(new impl_type<F>(std::move(f))) { }

    void operator()() { _impl->call(); }
    function_wrapper() = default;
    function_wrapper(function_wrapper &&rhs) : _impl(std::move(rhs._impl)) {}
    function_wrapper &operator=(function_wrapper &&rhs) 
    {
        _impl = std::move(rhs._impl);
        return *this;
    }

    function_wrapper(const function_wrapper &) = delete;
    function_wrapper(function_wrapper &) = delete;
    function_wrapper &operator=(const function_wrapper) = delete;
};

#endif